/*
 * @(#)NoticeManager.java
 * 2012-9-4 下午06:01:44
 * 
 *
 * Copyright (c) 2018-2028, HangZhou QiYun InfoTech Co.,Ltd. .
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.qyxx.platform.sysmng.notice.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.qyxx.platform.common.orm.Page;
import com.qyxx.platform.common.orm.PropertyFilter;
import com.qyxx.platform.sysmng.accountmng.dao.OrganizationDao;
import com.qyxx.platform.sysmng.accountmng.dao.RoleDao;
import com.qyxx.platform.sysmng.accountmng.dao.UserDao;
import com.qyxx.platform.sysmng.notice.dao.NoticeDao;
import com.qyxx.platform.sysmng.notice.dao.NoticeToUserDao;
import com.qyxx.platform.sysmng.notice.entity.Notice;
import com.qyxx.platform.sysmng.notice.entity.NoticeToUser;


/**
 *  
 *  @author ly
 *  @version 1.0 2012-9-4 下午06:01:44
 *  @since jdk1.6 
 */
@Component
@Transactional
public class NoticeManager {
	private static final String FIND_CURRENTUSER_NOTICES="select new Notice(b,a) from NoticeToUser a inner join a.notice b where b.status = ? and a.userId =?";
	private static final String FIND_NOREAD_NOTICES="select new Notice(b,a) from NoticeToUser a inner join a.notice b where b.status = ? and a.status= ? and a.userId =?";
    private static final String FIND_NOTICE_BY_USERID="select a from Notice a where a.createUser = ? and a.style = ?";
	private static final String FIND_NOTICE_ORDERBY_TYPE="select b.style,count(b) from NoticeToUser a inner join a.notice b where b.status = ? and a.status= ? and a.userId =? group by b.style";
	private static final String FIND_CURRENTUSER_NOTICE_BY_ID="select new Notice(b,a) from NoticeToUser a inner join a.notice b where b.id = ? and a.userId = ?";
	
	private static final String FIND_ALLUSER_NOREAD_NOTICES="select a from NoticeToUser a inner join a.notice b where b.status = ? and a.status= ?";
	private static final String FIND_NOREAD_NOTICES_COUNT_GROUP_BY_USER="select new map(a.userId as userId,count(a.userId) as count) from NoticeToUser a inner join a.notice b where b.status = ? and a.status= ? group by a.userId";
	
	private static final String FIND_NOREAD_NOTICE_BY_COND = "select b.id from NoticeToUser a inner join a.notice b " 
														+ "where b.status = ? and a.status= ? and a.userId =? and b.style = ? and b.title = ? and b.content = ?";
	
	private NoticeDao noticeDao;
    private NoticeToUserDao noticeToUserDao;
    private OrganizationDao organizationDao;
    private UserDao userDao;
    private RoleDao roleDao;
    
	public UserDao getUserDao() {
		return userDao;
	}
	@Autowired
	public void setUserDao(UserDao userDao) {
		this.userDao = userDao;
	}

	/**
	 * @return roleDao
	 */
	public RoleDao getRoleDao() {
		return roleDao;
	}
	
	/**
	 * @param roleDao
	 */
	@Autowired
	public void setRoleDao(RoleDao roleDao) {
		this.roleDao = roleDao;
	}
	
	@Autowired
    public void setNoticeDao(NoticeDao noticeDao) {
		this.noticeDao = noticeDao;
	}
    @Autowired
	public void setNoticeToUserDao(NoticeToUserDao noticeToUserDao) {
		this.noticeToUserDao = noticeToUserDao;
	}
    @Autowired
	public void setOrganizationDao(OrganizationDao organizationDao) {
		this.organizationDao = organizationDao;
	}
	
	public OrganizationDao getOrganizationDao() {
		return organizationDao;
	}
	
	public NoticeDao getNoticeDao() {
		return noticeDao;
	}

	public NoticeToUserDao getNoticeToUserDao() {
		return noticeToUserDao;
	}

	/**
	 * 保存一条通知
	 * 
	 * @param notice
	 * @param userId
	 */
	public void saveNotice(Notice notice,Long userId){
		//修改一条新闻
		if(notice.getId()!=null){
			notice.setLastUpdateUser(userId);
			notice.setLastUpdateTime(new Date());
		}else{//新增一条新闻
			notice.setCreateUser(userId);
			notice.setCreateTime(new Date());
			
		}
		
    	noticeDao.save(notice);
    	//清空用户通知中的通知id
    	noticeToUserDao.deleteByNoticeId(notice.getId());
    	String ids = notice.getNoticeToUserIds();
    	if (StringUtils.isNotBlank(ids)) {
			String id[] = ids.split(",");
			for (String x : id) {
				Long nToUserId=Long.parseLong(x);
				NoticeToUser ntu = new NoticeToUser();
		    	ntu.setNotice(notice);
		    	ntu.setUserId(nToUserId);
		    	ntu.setStatus("0");
		    	//notice.getNoticeToUserList().add(ntu);
		    	noticeToUserDao.save(ntu);
			}
		}
    	
	}
	
	/**
	 * 
	 * 更新NoticeToUser的阅读状态
	 * @param ntu
	 * @param userId
	 * @param status
	 */
	public void saveNoticeToUser(NoticeToUser ntu){
		ntu.setReadTime(new Date());
		ntu.setStatus(NoticeToUser.STATUS_1);
		noticeToUserDao.save(ntu);
	}
	
	/**
	 * 读1条消息
	 * 
	 * @param noticeToUserId
	 */
	public void readNotice(Long noticeToUserId) {
		NoticeToUser ntu=this.findNtuById(noticeToUserId);
		this.saveNoticeToUser(ntu);
	}
	
	/**
	 * 读通知
	 * 
	 * @param noticeId
	 * @param userId
	 * @param isReadAll 表示是否将整条通知，设置成全部人员已读
	 */
	public void readNotice(Long noticeId, Long userId, Boolean isReadAll){
		List<PropertyFilter> pfList = new ArrayList<PropertyFilter>();
		pfList.add(new PropertyFilter("EQL_notice.id",String.valueOf(noticeId)));
		pfList.add(new PropertyFilter("EQS_status",NoticeToUser.STATUS_0));
		if(!isReadAll) {
			pfList.add(new PropertyFilter("EQL_userId",String.valueOf(userId)));
		}
		List<NoticeToUser> ntuList = noticeToUserDao.find(pfList);
		if(null!=ntuList && !ntuList.isEmpty()) {
			for(NoticeToUser ntu : ntuList) {
				ntu.setReadTime(new Date());
				ntu.setStatus(NoticeToUser.STATUS_1);
				noticeToUserDao.save(ntu);
			}
		}
	}
	
	/**
	 * 更新新闻中的附件
	 * 
	 * @param newsId
	 * @param attachId
	 */
	public void updateNotice(Long noticeId,Long attachId){
		Notice notice=noticeDao.get(noticeId);
		notice.setAtmId(attachId);
	}
	/**
	 * 撤销通知
	 * 将通知状态置为草稿，删除用户通知关系表中的关系（可以不删除）
	 * 
	 * @param notice
	 * @param userId
	 * @param status
	 */
	public void repealNotice(final Long noticeId,Long userId,String status){
		Notice notice=noticeDao.get(noticeId);
		notice.setLastUpdateUser(userId);
		notice.setLastUpdateTime(new Date());
		notice.setStatus(status);
		//noticeDao.save(notice);
		//noticeToUserDao.deleteByNoticeId(notice.getId());
		

	}
	
	/**
	 * 查询通知列表
	 * 
	 * @param page
	 * @param filters
	 * @return
	 */
	@Transactional(readOnly = true)
    public  Page<Notice> findNoticeList(Page<Notice> page, List<PropertyFilter> filters){
		return this.preHandlePage(noticeDao.findPage(page, filters));
    }
	
	/**
	 * 查询当前用户发的所有通知
	 * @param page
	 * @param userId
	 * @return
	 */
	public Page<Notice> findNoticeListByUserId(Page<Notice> page,Long userId){
		return noticeDao.findPage(page,FIND_NOTICE_BY_USERID,userId,Notice.STYLE_01);
	}
	
	
	/**
	 * 
	 * 删除通知，先要删除用户通知关系表中的关系
	 * @param ids
	 */
	 public void deleteNotices(Long[] ids){
	    	for(Long id : ids){
	    		//删除与用户的关系
	    		noticeToUserDao.deleteByNoticeId(id);
	    		//删除通知
	    		noticeDao.delete(id);
	    	}
	    	
	 }
	 
	 
	 /**
	  * 根据id查找一条通知
	  * 
	  * @param id
	  * @return
	  */
	public Notice findById(Long id){
		Notice entity = noticeDao.get(id);
		List<NoticeToUser> ntu = entity.getNoticeToUserList();
		if (ntu != null && !ntu.isEmpty()) {
			for (NoticeToUser n : ntu) {
				entity.getUserIds().add(n.getUserId());
			}
		}
		entity.setNoticeToUserIds(StringUtils.join(entity.getUserIds(), ","));
		return entity;

	}

	
	/**
	 * 查询该通知下所有的用户关联的NoticeToUser实体集合
	 * 
	 * @param id
	 * @return
	 */
	public List<NoticeToUser> findNoticeDetail(Long id){
		Notice entity = noticeDao.get(id);
		List<NoticeToUser> ntus=entity.getNoticeToUserList();
		return this.preHandleNtuList(ntus);
	}
	

	
  /**
	 * 根据id查找一个NoticeToUser对象
	 * 
	 * @param id
	 * @return
	 */
	public NoticeToUser findNtuById(Long id){
		NoticeToUser entity=noticeToUserDao.get(id);
		return entity;
	}
	
	
	public NoticeToUser findNtuByUserId(List<Long> ids){
		
		
		
		return null;
	}
	
	/**
	 * 根据当前用户id查询所有通知的id
	 * 
	 * @param userId
	 */
	public Page<Notice> findAllNoticeToUser(Page<Notice> page, Long userId){
		return noticeDao.findPage(page, FIND_CURRENTUSER_NOTICES, Notice.STATUS_1, userId);
	
	}
	
	
	
	/**
	 * 查询当前用户未读的所有通知
	 * @param userId
	 * @return
	 */
//	public List<Notice> findNoReadNotice(Long userId){
//		return noticeDao.find(FIND_NOREAD_NOTICES, Notice.STATUS_1,NoticeToUser.STATUS_0, userId);
//	}
	
	/**
	 * 查询所有用户未读的所有通知
	 * @param 
	 * @return
	 */
	public List<NoticeToUser> findAllUserNoReadNotice() {
		return noticeToUserDao.find(FIND_ALLUSER_NOREAD_NOTICES, Notice.STATUS_1, NoticeToUser.STATUS_0);
	}
	
	/**
	 * 按userId分组查询所有未读的通知数量
	 * @param 
	 * @return
	 */
	public List<Object> findNoReadNoticeCount() {
		return noticeToUserDao.find(FIND_NOREAD_NOTICES_COUNT_GROUP_BY_USER, Notice.STATUS_1, NoticeToUser.STATUS_0);
	}
	
	/**
	 * 查询当前用户未读的所有通知
	 * @param userId
	 * @return
	 */
	public Page<Notice> findNoReadNotice(Page<Notice> page,List<PropertyFilter> filters,Long userId){
		return preHandlePage(noticeDao.findPage(FIND_NOREAD_NOTICES,page,filters,Notice.STATUS_1,NoticeToUser.STATUS_0, userId));
	}
	
	/**
	 * 查询当前用户未读的所有通知的数量
	 * @param userId
	 * @return
	 */
	public Long  findNoReadNoticeNumber(Page<Notice> page,Long userId){
		page = noticeDao.findPage(page,FIND_NOREAD_NOTICES,Notice.STATUS_1,NoticeToUser.STATUS_0, userId);
		return page.getTotalCount();	
	}
	
	/**
	 * 查询当前用户未读通知分类和数量
	 * @param userId
	 * @return
	 */
	public List<Object[]> findNoReadNoticeOrderByType(Long userId){
		return noticeDao.find(FIND_NOTICE_ORDERBY_TYPE, Notice.STATUS_1,NoticeToUser.STATUS_0, userId);
	}
	
	/**
	 * 分页查询用户接受到的通知
	 * 
	 * @param page
	 * @param userId
	 * @param filters
	 * @return
	 */
	public Page<Notice> findAllNoticeToUser(Page<Notice> page, Long userId, List<PropertyFilter> filters){
		return this.preHandlePage(noticeDao.findPage(FIND_CURRENTUSER_NOTICES, page, filters, Notice.STATUS_1, userId));
	}
	
	/**
	 * 公用发送通知方法，发送到人
	 * 
	 * @param title
	 * @param style
	 * @param moduleDataId
	 * @param moduleKey
	 * @param moduleFields
	 * @param userIdList
	 */
	public void sendNotice(String title,String style,String moduleDataId,String moduleKey,String moduleFields,List<Long> userIdList){
		if(null!=userIdList && !userIdList.isEmpty()) {
			for(Long userId : userIdList) {
				//根据用户、标题、内容查找相同通知
				List<Object> list = noticeDao.find(FIND_NOREAD_NOTICE_BY_COND, Notice.STATUS_1,
						NoticeToUser.STATUS_0, userId, style, title, title);
				if(list!=null && !list.isEmpty()) {
					//如果存在未读通知，则更新最后修改时间
					Long id = ((Number)list.get(0)).longValue();
					Notice notice = noticeDao.get(id);
					notice.setLastUpdateTime(new Date());
					notice.setLastUpdateUser(1L);
				} else {
					//每个用户生成1条消息
					Notice notice = new Notice();
					notice.setKeyworlds("提醒");
					notice.setTitle(title);
					notice.setStatus(Notice.STATUS_1);
					notice.setStyle(style);					
					notice.setCreateUser(1L);
					notice.setCreateTime(new Date());
					notice.setContent(title);
					notice.setModuleDataId(moduleDataId);
					notice.setModuleKey(moduleKey);
					notice.setModuleFields(moduleFields);
					noticeDao.save(notice);
					
					NoticeToUser noticeToUser = new NoticeToUser();
					noticeToUser.setNotice(notice);
					noticeToUser.setStatus(NoticeToUser.STATUS_0);
					noticeToUser.setUserId(userId);
					noticeToUserDao.save(noticeToUser);
				}
			}
		}
	}
	
	/**
	 * 公用发送通知方法，发送至角色下的人
	 * 角色名称使用英文逗号隔开
	 * 
	 * @param title
	 * @param style
	 * @param moduleDataId
	 * @param moduleKey
	 * @param moduleFields
	 * @param userIdList
	 */
	public void sendNotice(String title,String style,String moduleDataId,String moduleKey,String moduleFields,String roleName){
		if(StringUtils.isNotBlank(roleName)) {
			String[] roleNames = roleName.split(",");
			List<Long> userIdList = roleDao.findUserIdByRoleNames(roleNames);
			this.sendNotice(title, style, moduleDataId, moduleKey, moduleFields, userIdList);
		}
	}
	
	/**
	 * 根据通知ID和用户ID获取当前通知及通知阅读状态信息
	 * 
	 * @param noticeId
	 * @param userId
	 * @return
	 */
	public Notice findNoticeByIdAndUserId(Long noticeId, Long userId) {
		return preHandleObj((Notice)noticeDao.findUnique(FIND_CURRENTUSER_NOTICE_BY_ID, noticeId, userId));
	}
	
	
	/**
	 * 处理Page对象，翻译字段
	 * 
	 * @param page
	 * @return
	 */
	public Page<Notice> preHandlePage(Page<Notice> page) {
		List<Notice> list = page.getResult();
		if(list != null) {
			for(Notice n : list) {
				n.setCreateUserCaption(userDao.getUserNameById(n.getCreateUser()));
			}
		}
		return page;
	}
	
	/**
	 * 预处理对象，翻译字段
	 * 
	 * @param obj
	 * @return
	 */
	public Notice preHandleObj(Notice obj) {
		if(obj != null) {
			obj.setCreateUserCaption(userDao.getUserNameById(obj.getCreateUser()));
		}
		return obj;
	}
	
	/**
	 * 处理Page对象，翻译字段
	 * 
	 * @param page
	 * @return
	 */
	public Page<NoticeToUser> preHandleNtuPage(Page<NoticeToUser> page) {
		List<NoticeToUser> list = page.getResult();
		if(list != null) {
			for(NoticeToUser n : list) {
				n.setUserName(userDao.getUserNameById(n.getUserId()));
			}
		}
		return page;
	}
	
	/**
	 * 处理Page对象，翻译字段
	 * 
	 * @param page
	 * @return
	 */
	public List<NoticeToUser> preHandleNtuList(List<NoticeToUser> list) {
		if(list != null) {
			for(NoticeToUser n : list) {
				n.setUserName(userDao.getUserNameById(n.getUserId()));
			}
		}
		return list;
	}
	
	/**
	 * 预处理对象，翻译字段
	 * 
	 * @param obj
	 * @return
	 */
	public NoticeToUser preHandleObj(NoticeToUser obj) {
		if(obj != null) {
			obj.setUserName(userDao.getUserNameById(obj.getUserId()));
		}
		return obj;
	}
	
}
